package com.smt.modules.bus.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.IService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.smt.common.utils.AliyunOSSUtil;
import com.smt.common.utils.Constant;
import com.smt.common.utils.StringUtil;
import com.smt.modules.bus.dao.LocalRemoteDao;
import com.smt.modules.bus.entity.AttachmentEntity;
import com.smt.modules.bus.entity.LocalRemoteEntity;
import com.smt.modules.bus.service.AttachmentService;
import com.smt.modules.bus.service.LocalRemoteService;
import com.smt.modules.bus.vo.request.ProjectSiReq;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.data.convert.JodaTimeConverters;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.constraints.NotNull;
import java.io.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

/**
 * @author zhangyi
 * @date 2018/11/21 9:58
 */
@Service
@Slf4j
@ConfigurationProperties(prefix = "localstrategy")
public class LocalRemoteServiceImpl extends ServiceImpl<LocalRemoteDao, LocalRemoteEntity> implements LocalRemoteService {

    @Autowired
    private AliyunOSSUtil aliyunOSSUtil;

    @Autowired
    private AttachmentService attachmentService;
    /**
     * 文件保存本地服务器地址
     */
    private String localpath1;
    /**
     * 文件参照
     */
    private String localpath2;
    /**
     * 文件远程访问地址
     */
    private String linkpath;


    @Override
    public String localSaveFile(MultipartFile file, Long userId,ProjectSiReq projectSiReq) {
        DateTime now = DateTime.now();
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String format = dateFormat.format(now.toDate());
        String preStr = UUID.randomUUID().toString().replace("-","");
        String originalFilename = file.getOriginalFilename();
        FileInputStream fis = null;
        FileOutputStream fos = null;
        String fileLoadPath = null;
        try {
            //拼接字符串形成字符串
            File localPath = new File(localpath1+File.separator + userId + File.separator + format + File.separator);
            File localPathCopy = new File(localpath2+File.separator + userId + File.separator + format + File.separator);
            if (!localPath.isDirectory()) {
                localPath.mkdirs();
            }
            if (!localPathCopy.isDirectory()) {
                localPathCopy.mkdirs();
            }
            File localFile = new File(localPath.toString()+File.separator + preStr + Constant.FILE_SPILT + originalFilename);
            File localCopyFile = new File(localPathCopy.toString()+File.separator + preStr + Constant.FILE_SPILT + originalFilename);
            if (!localFile.isFile()) {
                localFile.createNewFile();
            }
            if (!localCopyFile.isFile()) {
                localCopyFile.createNewFile();
            }
            fis = (FileInputStream) file.getInputStream();
            fos = new FileOutputStream(localFile);
            Integer copy = IOUtils.copy(fis, fos);
            log.info("文件传输大小：{}", copy);
            fileLoadPath = linkpath + userId + File.separator + format + File.separator + preStr + Constant.FILE_SPILT + originalFilename;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                fis.close();
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        localFileUpdate(fileLoadPath,null,userId,projectSiReq);
        return fileLoadPath;
    }

    /**
     * 异步存储文件路径
     *
     * @param file
     * @param userId
     * @return
     */
    @Async
    @Override
    public String remoteSaveFile(MultipartFile file, Long userId,ProjectSiReq projectSiReq) {
        String filePath = null;
        try {
            filePath = aliyunOSSUtil.upload(file.getInputStream(),
                    new File(file.getOriginalFilename()),
                    String.valueOf(userId));
        } catch (IOException e) {
            e.printStackTrace();
        }
        RemoteFileUpdate(null,filePath,userId,projectSiReq);
        return filePath;
    }

    /**
     * 获取文件路径
     *
     * @param projectSiReq
     * @return
     */
    @Override
    public String getFileUrl(ProjectSiReq projectSiReq) {
        LocalRemoteEntity localRemoteEntity = selectOne(getFileWrapper(projectSiReq));
        if(Objects.isNull(localRemoteEntity)){
            return "无效路径";
        }else{
            String localPath = localRemoteEntity.getLocalPath();
            String remote = localRemoteEntity.getRemote();
            return Objects.isNull(localPath)?remote:localPath;
        }
    }


    /**
     * 远程更新文件信息
     *
     * @param localPath
     * @param remotePath
     * @param userId
     * @param projectSiReq
     */
    private void RemoteFileUpdate(String localPath, String remotePath,Long userId,ProjectSiReq projectSiReq){
        Long projectId = projectSiReq.getProjectId();
        Long taskId = projectSiReq.getTaskId();
        Long subTaskId = projectSiReq.getSubTaskId();
        Wrapper<AttachmentEntity> projectAttachment = new EntityWrapper<AttachmentEntity>()
                .eq("project_id", projectId);
        //存储文件信息
        LocalRemoteEntity localRemoteEntity = new LocalRemoteEntity(localPath,remotePath,userId,DateTime.now().toDate());
        boolean update = update(localRemoteEntity, getFileWrapper(projectSiReq));
        log.info("文件上传到OSS上的状态：{}",update);
        //更新文件的真实下载路径
        if(!Objects.isNull(taskId)){
            projectAttachment.eq("project_task_id", taskId);
        }else if(!Objects.isNull(subTaskId)){
            projectAttachment.eq("project_sub_task_id", subTaskId);
        }
        AttachmentEntity attachmentEntity = null;
        List<AttachmentEntity> attachmentEntities = attachmentService.selectList(projectAttachment.orderBy("create_time", false));
        if(attachmentEntities != null && attachmentEntities.size() != 0){
            attachmentEntity = attachmentEntities.get(0);
            attachmentEntity.setUrl(remotePath);
            boolean b = attachmentService.updateById(attachmentEntity);
            log.info("文件真实地址更新状态：{}",b);
        }
        log.info("文件更新完毕... 删除本地临时文件");
        LocalRemoteEntity localRemoteE = selectOne(getFileWrapper(projectSiReq));
//     ...
    }

    /**
     * 本地保存文件映射
     *
     * @param localPath
     * @param remotePath
     * @param userId
     */
    private void localFileUpdate(String localPath, String remotePath,Long userId,ProjectSiReq projectSiReq){
        LocalRemoteEntity localRemoteE = selectOne(getFileWrapper(projectSiReq));
        //本地文件为空
        if(Objects.isNull(localRemoteE)){
            //第一次插入
            LocalRemoteEntity localRemoteEntity = new LocalRemoteEntity(localPath,remotePath,userId,projectSiReq,DateTime.now().toDate());
            insert(localRemoteEntity);
        }else{
            //更新文件插入信息
            String local = localRemoteE.getLocalPath();
            if(!Objects.isNull(local)){
                String delLocalFile = localRemoteE.getLocalPath();
                if(!Objects.isNull(delLocalFile)){
                    //去除本地文件
                    File file = new File(delLocalFile);
                    if(file.isFile()){
                        file.delete();
                    }
                }
                localRemoteE.setLocalPath(localPath);
                updateById(localRemoteE);
            }
        }

    }

    /**
     * 返回封装查询类
     *
     * @param projectSiReq
     * @return
     */
    private Wrapper<LocalRemoteEntity> getFileWrapper(ProjectSiReq projectSiReq){
        Long taskId = projectSiReq.getTaskId();
        Long subTaskId = projectSiReq.getSubTaskId();
        Wrapper<LocalRemoteEntity> eq = new EntityWrapper<LocalRemoteEntity>()
                .eq("project_id", projectSiReq.getProjectId())
                .eq("stage_id", projectSiReq.getStage());
        if(!taskId.equals(-1)){
            eq.eq("task_id", taskId);
        }else if(!subTaskId.equals(-1)){
            eq.eq("sub_task_id", subTaskId);
        }
        return eq;
    }

    public String getLocalpath1() {
        return localpath1;
    }

    public void setLocalpath1(String localpath1) {
        this.localpath1 = localpath1;
    }

    public String getLocalpath2() {
        return localpath2;
    }

    public void setLocalpath2(String localpath2) {
        this.localpath2 = localpath2;
    }

    public String getLinkpath() {
        return linkpath;
    }

    public void setLinkpath(String linkpath) {
        this.linkpath = linkpath;
    }
}
